package aliyun

import (
	"fmt"
	"github.com/aliyun/aliyun-oss-go-sdk/oss"
	"github.com/pkg/errors"
	"my-new-gin/utils"
	"io/ioutil"
	"my-new-gin/configs"
	"net/http"
	"os"
	"strings"
	"time"
)
var (
	bucket_name string
	img_folder string
	video_folder string
	file_folder string
	endpoint string
	accessKeyId string
	accessKeySecret string
)
var client *oss.Client
func init()  {
	aliyunAccessKeyConf := configs.GetAliyunAccessKeyConf()
	accessKeyId = aliyunAccessKeyConf.AccessKeyId
	accessKeySecret = aliyunAccessKeyConf.AccessKeySecret

	AliyunOssConf := configs.GetAliyunOssConf()
	endpoint = AliyunOssConf.Endpoint
	file_folder = AliyunOssConf.FileFolder
	video_folder = AliyunOssConf.VideoFolder
	img_folder = AliyunOssConf.ImgFolder
	bucket_name = AliyunOssConf.BucketName

	cli, err := oss.New(endpoint, accessKeyId, accessKeySecret)
	if err != nil {
		fmt.Println("OSS Error:", err)
		cli = nil
		return
	}
	client = cli
}
func getBucket() (*oss.Bucket, error) {
	if client != nil {
		return client.Bucket(bucket_name)
	}
	return nil, errors.New("client is nil")
}

func OssUploadImage(filename string, fileByte *os.File) (objName string, err error) {
	arr := strings.Split(filename,".")
	extName := strings.ToLower(arr[len(arr)-1])
	if extName == "jpg" || extName == "png" || extName == "gif" {
		bucket, err := getBucket()
		if err != nil {
			fmt.Printf("Get OSS Bucket ERROR : %v \n", err)
			return "", fmt.Errorf("Get OSS Bucket ERROR : %v \n", err)
		}
		err = bucket.PutObject(img_folder+filename, fileByte)
		if err != nil {
			fmt.Printf("OSS Upload Error: %v \n", err)
			return "", fmt.Errorf("OSS Upload Error: %v \n", err)
		}
		return img_folder + filename, nil
	}
	return "", errors.New("file extName error")
}

func OssUploadVideo(filename string, fileByte *os.File) (objName string, err error) {
	arr := strings.Split(filename,".")
	extName := strings.ToLower(arr[len(arr)-1])
	if extName == "jpg" || extName == "png" || extName == "gif" {
		bucket, err := getBucket()
		if err != nil {
			fmt.Printf("Get OSS Bucket ERROR : %v \n", err)
			return "", fmt.Errorf("Get OSS Bucket ERROR : %v \n", err)
		}
		err = bucket.PutObject(video_folder+filename, fileByte)
		if err != nil {
			fmt.Printf("OSS Upload Error: %v \n", err)
			return "", fmt.Errorf("OSS Upload Error: %v \n", err)
		}
		return video_folder + filename, nil
	}
	return "", errors.New("file extName error")
}

func GetOssImgUrl(objName string) string {
	if strings.HasPrefix(objName,"/") {
		return "https://file.891806797.com"+objName
	}
	return "https://file.891806797.com/"+objName
}

type T1 struct {
	Value      string  `json:"value"`
	Confidence float32 `json:"confidence"`
}

type T2 struct {
	Tags []T1 `json:"tags"`
}

func GetImageTags(img_url string) (string, error) {
	host := "dtplus-cn-shanghai.data.aliyuncs.com"
	path := "/image/tag"
	body := struct {
		Type     int    `json:"type"`
		ImageUrl string `json:"image_url"`
	}{0, img_url}
	jsonBody, err := utils.Struct2Json(body)
	if err != nil {
		return "", err
	}
	md5Body := utils.GetMD5(jsonBody)
	timeStr := time.Now().UTC().String()
	stringToSign := "POST\n" +
		"application/json\n" +
		md5Body + "\n" +
		"application/json\n" +
		timeStr + "\n" +
		path

	signature := utils.GetShe1ByKey(stringToSign, accessKeySecret)
	req, err := http.NewRequest(http.MethodPost, "https://"+host+path, strings.NewReader(jsonBody))
	req.Header.Add("accept", "application/json")
	req.Header.Add("content-type", "application/json")
	req.Header.Add("Authorization", "Dataplus "+accessKeyId+":"+signature)
	req.Header.Add("date", timeStr)
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()
	bodyByte, err := ioutil.ReadAll(resp.Body)
	var obj = new(T2)
	_, err = utils.Json2Struct(string(bodyByte), obj)
	if err != nil {
		return "", err
	}
	tags := ""
	for _, v := range obj.Tags {
		tags += v.Value + ","
	}
	return tags[:len(tags)-1], nil
}

type FileInfo1 struct {
	FileSize struct{
		Value string `json:"value"`
	} `json:"FileSize"`
	ImageWidth struct{
		Value string `json:"value"`
	} `json:"ImageWidth"`
	ImageHeight struct{
		Value string `json:"value"`
	} `json:"ImageHeight"`
}

type FileInfo2 struct {
	RGB string `json:"RGB"`
}

type FileInfo struct {
	FileInfo1
	FileInfo2
}
func GetOssFileInfo(ObjName string) (info FileInfo, err error) {
	url := GetOssImgUrl(ObjName)
	resp1, err := http.Get(fmt.Sprintf("%s?x-oss-process=image/info",url))
	if err != nil {
		return FileInfo{}, err
	}
	defer resp1.Body.Close()
	bodyByte1, err := ioutil.ReadAll(resp1.Body)
	if err != nil {
		return FileInfo{}, err
	}

	resp2, err := http.Get(fmt.Sprintf("%s?x-oss-process=image/average-hue",url))
	if err != nil {
		return FileInfo{}, err
	}
	defer resp2.Body.Close()
	bodyByte2, err := ioutil.ReadAll(resp2.Body)
	if err != nil {
		return FileInfo{}, err
	}

	var fileInfo1 = new(FileInfo1)
	var fileInfo2 = new(FileInfo2)
	_, err = utils.Json2Struct(string(bodyByte1),fileInfo1)
	_, err = utils.Json2Struct(string(bodyByte2),fileInfo2)
	info = FileInfo{
		*fileInfo1,
		*fileInfo2,
	}
	return info,err
}